package com.njmaomao.gj.pyot.config;

import com.njmaomao.gj.pyot.common.ResponseCode;
import com.njmaomao.gj.pyot.common.exception.SystemBizFail;
import com.njmaomao.gj.pyot.domain.wechat.PayConfig;
import com.njmaomao.gj.pyot.domain.wechat.PayConfigFactory;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

@Component
public class CertRestTemplateFactory {

    private Logger log = LoggerFactory.getLogger(CertRestTemplateFactory.class);

    private final Map<String, RestTemplate> restTemplateMap = new HashMap<>();

    @Autowired
    private PayConfigFactory payConfigFactory;

    private RestTemplate certRestTemplate(String mchId, String certLocal) throws Exception {

        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        char[] password = mchId.toCharArray();

        try (InputStream in = this.getClass().getResourceAsStream(certLocal)) {
            keyStore.load(in, password);
        }

        SSLContext sslContext = SSLContextBuilder.create()
                .loadKeyMaterial(keyStore, password)
                .build();

        HttpClient client = HttpClients.custom().setSSLContext(sslContext).setRetryHandler((exception, executionCount, context) -> {
            if (executionCount <= 3) {
                log.warn("restTemplate 调用异常:{}, 第{}次重试", exception.getMessage(), executionCount);
                return true;
            }
            return false;
        }).build();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
        requestFactory.setConnectTimeout(5000);
        requestFactory.setReadTimeout(5000);
        requestFactory.setConnectionRequestTimeout(3000);
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
        return restTemplate;
    }

    /**
     * 获取支付配置
     * @param appId
     * @return
     */
    public synchronized RestTemplate get(String appId) {
        RestTemplate restTemplate = restTemplateMap.get(appId);

        if(restTemplate == null) {
            PayConfig payConfig = payConfigFactory.get(appId, null);
            try {
                restTemplate = certRestTemplate(payConfig.getMchId(), payConfig.getCertLocal());
                restTemplateMap.put(appId, restTemplate);
            } catch (Exception e) {
                log.error("CertRestTemplateFactory get " + appId, e);
                SystemBizFail.happen(ResponseCode.PAYTO.CERTRESTTEMPLATE_ERROR);
            }
        }

        return restTemplate;
    }

}
